/*
 * readline.h
 *
 *  Created on: Jul 28, 2010
 *      Author: Pierre Lindenbaum PhD
 *              plindenbaum@yahoo.fr
 *              http://plindenbaum.blogspot.com
 *              
 */

#ifndef U915_IO_GZSTREAMBUF_H_
#define U915_IO_GZSTREAMBUF_H_
#include <string>
#include <iostream>
#include <stdexcept>
#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <sstream>
#include <zlib.h>
#include "core/io/istreambuf.h"



namespace u915 { namespace io {
/**
* buffer reading a gz file
*/
class gzinbuf : public u915::io::istreambuf
    {
    private:
	gzFile source;

	void _close()
	    {
	    if(source!=NULL)
		{
		::gzclose(source);
		source=NULL;
		}
	    }

    public:
	gzinbuf(const char *path,int buff_size=BUFSIZ): u915::io::istreambuf(buff_size),
	    source(NULL)
		{
		errno=0;
		source=::gzopen(path,"rb");
		if(source==NULL)
		    {
		    std::ostringstream os;
		    os << "failed to open \"" << path<< "\" ("
			    << std::strerror(errno) << ").";
		    throw std::runtime_error(os.str());
		    }
		}

	virtual ~gzinbuf()
	    {
	    _close();
	    }


	virtual int underflow ( )
	    {
	    if(source==NULL) return EOF;
	    int nRead= ::gzread(this->source,(void*)this->buffer,this->buffer_capacity);
	    if(nRead<0)
		{
		throw std::runtime_error("I/O error");
		}
	    else if(nRead==0)
		{
		_close();
		return EOF;
		}
	    this->buffer_size=(unsigned int)nRead;
	    setg( (char*)this->buffer,
		(char*)&this->buffer[0],
		(char*)&this->buffer[this->buffer_size]
		);
	    return this->buffer_size==0?EOF:this->buffer[0];
	    }
    };



}}//namespaces



#endif /* TOKENIZER_H_ */
